#include "regionGrowing.hpp"
#define ECART 30
#define ECARTF 30

uchar* getP(IplImage* i,int x,int y)
{
	return (uchar*)(i->imageData)+(y*i->widthStep)+x*3;
}
bool testNB(IplImage* i)
{
	for(int y=0;y<i->height;y=y+1)
	{
		for(int x=0;x<i->width;x=x+1)
		{
			if(getP(i,x,y)[2]!=getP(i,x,y)[1] || getP(i,x,y)[0]!=getP(i,x,y)[1])
			{
				return false;
			}
		}
	}
	return true;
}
RegionGrowing::RegionGrowing(IplImage* i)
{
	tab = new Cellule[i->width*i->height];
	colorsRegion.push_back(Colors());
	img=cvCreateImage(cvSize(i->width,i->height),IPL_DEPTH_8U,i->nChannels);
	cvCvtColor( i, img, CV_BGR2HSV );
	noir=testNB(i);
}

RegionGrowing::~RegionGrowing()
{
	colorsRegion.clear();
	delete[] tab;
}

IplImage* RegionGrowing::getImg()
{
	return img;
}
Cellule* RegionGrowing::getTab()
{
	return tab;
}
vector<Colors> RegionGrowing::getColorsRegion()
{
	return colorsRegion;
}
Cellule RegionGrowing::getTabIndex(int x, int y)
{
	return tab[x*img->width+y];
}
Colors RegionGrowing::getColorsRegionIndex(int i)
{
	return colorsRegion[i];
}
uchar* RegionGrowing::getPixel(int x,int y)
{
	return (uchar*)(img->imageData)+(y*img->widthStep)+x*3;
}

void RegionGrowing::setImg(IplImage* i)
{
	img=i;
}
void RegionGrowing::setTab(Cellule* t)
{
	delete[] tab;
	tab=t;
}
void RegionGrowing::setColorsRegion(vector<Colors> cr)
{
	colorsRegion=cr;
}
void RegionGrowing::setTabIndex(Cellule c,int x, int y)
{
	tab[x*img->width+y]=c;
}
void RegionGrowing::setColorsRegionIndex(int i,int r,int g,int b)
{
	colorsRegion.push_back(Colors(r,g,b));
}
void RegionGrowing::setPixel(int x,int y,uchar r,uchar g,uchar b)
{
	((img->imageData)+(y*img->widthStep)+x*3)[0]=b;
	((img->imageData)+(y*img->widthStep)+x*3)[1]=g;
	((img->imageData)+(y*img->widthStep)+x*3)[2]=r;
}

void RegionGrowing::croissance()
{
	int nbV1;
	Cellule* tmp = new Cellule[img->width*img->height];
	for(int j=0;j<img->height;j++)
	{
		for(int i=0;i<img->width;i++)
		{
			tmp[j*img->width+i]=tab[j*img->width+i];
		}
	}
	do
	{
		nbV1=0;
		for(int j=0;j<img->height;j++)
		{
			for(int i=0;i<img->width;i++)
			{
				if(tab[j*img->width+i].getVisite()==1)
				{
					tmp[j*img->width+i].setVisite(2);
					nbV1--;
					for(int y=-1;y<=1;y++)
					{
						for(int x=-1;x<=1;x++)
						{
							if(i+x>=0 && i+x<img->width && j+y>=0 && j+y<img->height && tab[(j+y)*img->width+i+x].getVisite()==0)
							{
								if(colorsRegion[tab[j*img->width+i].getRegion()].comparaison((int)getPixel(i+x,j+y)[2],(int)getPixel(i+x,j+y)[1],(int)getPixel(i+x,j+y)[0],ECART,noir))
								{
									tmp[(j+y)*img->width+i+x].setVisite(1);
									tmp[(j+y)*img->width+i+x].setRegion(tab[j*img->width+i].getRegion());
									/*int testr = (getColorsRegionIndex(tab[j*img->width+i].getRegion()).getR() + getPixel(i+x,j+y)[2])/2;
									int testg = (getColorsRegionIndex(tab[j*img->width+i].getRegion()).getG() + getPixel(i+x,j+y)[1])/2;
									int testb = (getColorsRegionIndex(tab[j*img->width+i].getRegion()).getB() + getPixel(i+x,j+y)[0])/2;
									getColorsRegionIndex(tab[j*img->width+i].getRegion()).setR(testr);
									getColorsRegionIndex(tab[j*img->width+i].getRegion()).setG(testg);
									getColorsRegionIndex(tab[j*img->width+i].getRegion()).setB(testb);*/
									//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(getPixel(i+x,j+y)[2],getPixel(i+x,j+y)[1],getPixel(i+x,j+y)[0]);
									nbV1++;
								}
							}
						}
					}
				}
			}
		}
		for(int j=0;j<img->height;j++)
		{
			for(int i=0;i<img->width;i++)
			{
				tab[j*img->width+i]=tmp[j*img->width+i];
			}
		}
	}while(nbV1!=0);
}

void RegionGrowing::poseGerme()
{
	//for(int j=0;j<img->height;j=j+1)
	//{
		//for(int i=0;i<img->width;i=i+1)
		//{
			//colorsRegion.push_back(Colors(getPixel(i,j)[2],getPixel(i,j)[1],getPixel(i,j)[0]));
			//tab[j*img->width+i].setRegion(colorsRegion.size()-1);
			//tab[j*img->width+i].setVisite(1);
		//}
	//}
	recurtionInitialisation(0, 0, img->width, img->height);

}

void RegionGrowing::recurtionInitialisation(int x, int y, int sizeX, int sizeY)
{
	
	int h = (int)getPixel((x+sizeX/2),(y+sizeY/2))[0];//(int)img->imageData[(y+sizeY/2)*img->widthStep+(x+sizeX/2)*3];
	int s = (int)getPixel((x+sizeX/2),(y+sizeY/2))[1];//(int)img->imageData[(y+sizeY/2)*img->widthStep+(x+sizeX/2)*3+1];
	int v = (int)getPixel((x+sizeX/2),(y+sizeY/2))[2];//(int)img->imageData[(y+sizeY/2)*img->widthStep+(x+sizeX/2)*3+2];
	bool arret = false;
	int j = y;
	Colors c(v,s,h);
	if(sizeX>1  && sizeY>1)
	{
		while(!arret && j<y+sizeY && j<img->height-1)
		{
			int i=x;
			while(!arret && i<x+sizeX && i<img->width-1)
			{
				//if(!c.comparaison((int)img->imageData[j*img->widthStep+i*3+2],(int)img->imageData[j*img->widthStep+i*3+1],(int)img->imageData[j*img->widthStep+i*3],ECART))
				if(!c.comparaison((int)getPixel(i,j)[2],(int)getPixel(i,j)[1],(int)getPixel(i,j)[0],ECART,noir))
				{
					recurtionInitialisation(x,y, sizeX/2, sizeY/2);
					recurtionInitialisation(x+sizeX/2, y+sizeY/2, sizeX-(sizeX/2), sizeY-(sizeY/2));
					recurtionInitialisation(x+sizeX/2, y, sizeX-(sizeX/2), sizeY/2);
					recurtionInitialisation(x, y+sizeY/2, sizeX/2, sizeY-(sizeY/2));
					arret = true;
				}
				i++;
			}
			j++;
		}
		if(!arret)
		{
			int i = x+sizeX/2;
			j = y+sizeY/2;
			colorsRegion.push_back(Colors((int)getPixel(i,j)[2],(int)getPixel(i,j)[1],(int)getPixel(i,j)[0]));
			tab[j*img->width+i].setRegion(colorsRegion.size()-1);
			tab[j*img->width+i].setVisite(1);
		}
	}
	else
	{
		colorsRegion.push_back(Colors((int)getPixel(x,y)[2],(int)getPixel(x,y)[1],(int)getPixel(x,y)[0]));
		tab[y*img->width+x].setRegion(colorsRegion.size()-1);
		tab[y*img->width+x].setVisite(1);
	}
}

IplImage* RegionGrowing::rendu()
{
	IplImage* res=cvCreateImage(cvSize(img->width,img->height),img->depth,3);
	for(int j=0;j<img->height;j++)
	{
		for(int i=0;i<img->width;i++)
		{
			((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[0]=(uchar)colorsRegion[tab[j*img->width+i].getRegion()].getHR();
			((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[1]=(uchar)colorsRegion[tab[j*img->width+i].getRegion()].getSR();
			((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[2]=(uchar)colorsRegion[tab[j*img->width+i].getRegion()].getVR();
		}
	}
	
	IplImage* res2=cvCreateImage(cvSize(img->width,img->height),img->depth,3);
	cvCvtColor( res, res2, CV_HSV2BGR );
	return res2;
}

IplImage* RegionGrowing::frontiere(IplImage* image)
{
	IplImage* res=cvCreateImage(cvSize(image->width,image->height),image->depth,3);
	for(int j=0;j<image->height;j++)
	{
		for(int i=0;i<image->width;i++)
		{
			if(i!=image->width-1 &&
				((uchar*)(image->imageData)+(j*image->widthStep)+i*3)[0]!=((uchar*)(image->imageData)+(j*image->widthStep)+(i+1)*3)[0] &&
				((uchar*)(image->imageData)+(j*image->widthStep)+i*3)[1]!=((uchar*)(image->imageData)+(j*image->widthStep)+(i+1)*3)[1] &&
				((uchar*)(image->imageData)+(j*image->widthStep)+i*3)[2]!=((uchar*)(image->imageData)+(j*image->widthStep)+(i+1)*3)[2])
			{
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[0]=255;
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[1]=255;
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[2]=255;
			}
			else
			{
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[0]=0;
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[1]=0;
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[2]=0;
			}

			if(j!=image->height-1 &&
				((uchar*)(image->imageData)+(j*image->widthStep)+i*3)[0]!=((uchar*)(image->imageData)+((j+1)*image->widthStep)+i*3)[0] &&
				((uchar*)(image->imageData)+(j*image->widthStep)+i*3)[1]!=((uchar*)(image->imageData)+((j+1)*image->widthStep)+i*3)[1] &&
				((uchar*)(image->imageData)+(j*image->widthStep)+i*3)[2]!=((uchar*)(image->imageData)+((j+1)*image->widthStep)+i*3)[2])
			{
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[0]=255;
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[1]=255;
				((uchar*)(res->imageData)+(j*res->widthStep)+i*3)[2]=255;
			}
		}
	}
	return res;
}

void RegionGrowing::fusion()
{
	for(int j=0;j<img->height;j++)
	{
		for(int i=0;i<img->width;i++)
		{
			if(i!=img->width-1 && 
				tab[j*img->width+i].getRegion()!=tab[j*img->width+i+1].getRegion() &&
				tab[j*img->width+i+1].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[j*img->width+i+1].getRegion()],ECARTF,noir))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[j*img->width+i+1].getRegion()]);
				colorsRegion[tab[j*img->width+i+1].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);	
			}
			if(j!=img->height-1 && 
				tab[j*img->width+i].getRegion()!=tab[(j+1)*img->width+i].getRegion() &&
				tab[(j+1)*img->width+i].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[(j+1)*img->width+i].getRegion()],ECARTF,noir))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[(j+1)*img->width+i].getRegion()]);
				colorsRegion[tab[(j+1)*img->width+i].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);
			}
		}
	}

	for(int j=img->height-1;j>0;j--)
	{
		for(int i=img->width-1;i>0;i--)
		{
			if(i!=0 && 
				tab[j*img->width+i].getRegion()!=tab[j*img->width+i-1].getRegion() &&
				tab[j*img->width+i-1].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[j*img->width+i-1].getRegion()],ECARTF,noir))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[j*img->width+i-1].getRegion()]);
				colorsRegion[tab[j*img->width+i-1].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);	
			}
			if(j!=0 && 
				tab[j*img->width+i].getRegion()!=tab[(j-1)*img->width+i].getRegion() &&
				tab[(j-1)*img->width+i].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[(j-1)*img->width+i].getRegion()],ECARTF,noir))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[(j-1)*img->width+i].getRegion()]);
				colorsRegion[tab[(j-1)*img->width+i].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);
			}
		}
	}
/*
	for(int i=0;i<img->width;i++)
	{
		for(int j=0;j<img->height;j++)
		{
			if(i!=img->width-1 && 
				tab[j*img->width+i].getRegion()!=tab[j*img->width+i+1].getRegion() &&
				tab[j*img->width+i+1].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[j*img->width+i+1].getRegion()],50))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[j*img->width+i+1].getRegion()]);
				colorsRegion[tab[j*img->width+i+1].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);	
			}
			if(j!=img->height-1 && 
				tab[j*img->width+i].getRegion()!=tab[(j+1)*img->width+i].getRegion() &&
				tab[(j+1)*img->width+i].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[(j+1)*img->width+i].getRegion()],50))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[(j+1)*img->width+i].getRegion()]);
				colorsRegion[tab[(j+1)*img->width+i].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);
			}
		}
	}

	for(int i=img->width-1;i>0;i--)
	{
		for(int j=img->height-1;j>0;j--)
		{
			if(i!=img->width-1 && 
				tab[j*img->width+i].getRegion()!=tab[j*img->width+i-1].getRegion() &&
				tab[j*img->width+i-1].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[j*img->width+i-1].getRegion()],50))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[j*img->width+i+1].getRegion()]);
				colorsRegion[tab[j*img->width+i-1].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);	
			}
			if(j!=img->height-1 && 
				tab[j*img->width+i].getRegion()!=tab[(j-1)*img->width+i].getRegion() &&
				tab[(j-1)*img->width+i].getRegion()!=0 &&
				tab[j*img->width+i].getRegion()!=0 &&
				colorsRegion[tab[j*img->width+i].getRegion()].comparaison(colorsRegion[tab[(j-1)*img->width+i].getRegion()],50))
			{
				//colorsRegion[tab[j*img->width+i].getRegion()].moyenne(colorsRegion[tab[(j+1)*img->width+i].getRegion()]);
				colorsRegion[tab[(j-1)*img->width+i].getRegion()].setColors(colorsRegion[tab[j*img->width+i].getRegion()]);
			}
		}
	}*/

}